package org.mm.proxycache.http.codec;

import org.apache.mina.common.IoBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderException;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.mm.proxycache.http.HttpChunk;
import org.mm.proxycache.http.codec.HttpParser.ParserStatus;
import org.mm.proxycache.http.codec.HttpParser.ParserType;
import org.mm.proxycache.http.codec.HttpParser.State;

public class HttpResponseDecoder extends ProtocolDecoderAdapter
{
    
    public void decode( IoSession session, IoBuffer in, ProtocolDecoderOutput out )
            throws Exception
    {
        HttpParser parser = (HttpParser) session.getAttribute( DecoderName );
        if ( parser == null )
        {
            parser = new HttpParser( ParserType.ResponseParser );
            session.setAttributeIfAbsent( DecoderName, parser );
        }
        
        ParserStatus res = parser.decode( in );
        switch ( res )
        {
        case Error:
            throw new ProtocolDecoderException( "Error parsing HTTP response" );
            
        case Done:
        case NeedData:
            while ( true )
            {
                Object obj = parser.getParsed();
                if ( obj == null )
                    break;
                
                out.write( obj );
            }
            break;
        
        default:
            break;
        }
        
        if ( res == ParserStatus.Done )
            parser.reset();
    }
    
    @Override
    public void finishDecode( IoSession session, ProtocolDecoderOutput out ) throws Exception
    {
        HttpParser parser = (HttpParser) session.getAttribute( DecoderName );
        
        if ( parser != null && parser.state() == State.ReadBodyAdLibitum )
        {
            // Write the end message marker
            out.write( HttpChunk.lastChunk( parser.getMessage() ) );
        }
    }
    
    private static final String DecoderName = HttpResponseDecoder.class.getName();
    
}
